package com.winbomb.kingcard.base;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import android.graphics.Color;

import com.winbomb.kingcard.Action;
import com.winbomb.kingcard.GameMsg;
import com.winbomb.kingcard.IAttackRoute;
import com.winbomb.kingcard.ICard;
import com.winbomb.kingcard.ICardPile;
import com.winbomb.kingcard.IForce;
import com.winbomb.kingcard.IGameLogic;
import com.winbomb.kingcard.IPlayer;
import com.winbomb.kingcard.IPlayerInfo;
import com.winbomb.kingcard.IState;
import com.winbomb.kingcard.IStatsInfo;
import com.winbomb.kingcard.NoMoreCardException;
import com.winbomb.kingcard.Pos;
import com.winbomb.kingcard.utils.GameUtils;

public class Player implements IPlayer {

	/** 玩家的手牌 */
	protected List<ICard> cards;

	/** 玩家的战牌 */
	protected List<ICard> battleCards;

	/** 当前游戏 */
	protected IGameLogic game;

	/** 牌堆 */
	protected ICardPile cardPile;

	/** 玩家是否还健在 */
	private boolean isAlive;

	/** 本轮的动作 */
	private Action action;

	/** 是否是攻击者 */
	private boolean isAttacker;

	/** 攻击目标，指发起攻击时的被攻击者 */
	private IPlayer atkTarget;

	/** 进攻的路线 */
	private IAttackRoute atkRoute;

	/** 是否是防御者 */
	private boolean isDefender;

	/** 攻击源，指受到攻击时的发出攻击者 */
	private IPlayer atkSource;

	/** 势力 */
	private IForce force;

	/** 攻击的方向 */
	private boolean atkClockwise;

	/** 出牌时是否选了主将 */
	protected boolean hasGeneral;

	/** 玩家名称 */
	private String name;

	/** 头像编号 */
	private int portraitId;

	/** 位置，是指左上角点所在的坐标 */
	private Pos pos;

	/** 轮到本人的步骤是否完成 */
	private boolean isDone;

	/** 本回合出手的剩余时间 */
	private float timeLeft;

	/** 是电脑玩家还是人工玩家 */
	private boolean isHuman;

	/** 玩家信息 */
	private IPlayerInfo playerInfo;

	/** 在玩家中的坐标 */
	private int index;

	/** 统计信息 */
	private IStatsInfo statsInfo;

	/** 派遣的目标 */
	private IPlayer sendTarget;

	/** 征召的源 */
	private IPlayer callSource;

	/** 本回合的动作掩码 */
	private boolean[] actionMask;

	public Player(IGameLogic game, IPlayerInfo playerInfo, boolean isHuman) {
		this.game = game;
		this.cardPile = game.getCardPile();
		this.cards = new ArrayList<ICard>();
		this.battleCards = new ArrayList<ICard>();
		this.isAlive = true;
		this.hasGeneral = false;
		this.force = new Force(this);
		this.statsInfo = new StatsInfo(this);

		this.isHuman = isHuman;
		this.playerInfo = playerInfo;
		this.name = playerInfo.getName();

		this.actionMask = new boolean[5];
		this.isDone = false;
	}

	public String toString() {
		return this.name;
	}

	@Override
	public boolean isHuman() {
		return isHuman;
	}

	@Override
	public void drawCard() {

		if (cards.size() >= GameLogic.MAX_CARD_COUNT) {
			return;
		}

		// 从牌堆中抽一张牌
		ICard card;
		try {
			card = cardPile.drawCard();
			insertCard(card);
		} catch (NoMoreCardException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	public ICard[] playCards() {
		ICard[] marchCards = new ICard[GameLogic.MAX_PLAY_CARD];

		int cardCnt = 0;
		for (ICard card : cards) {
			if (card.isSelected()) {
				marchCards[cardCnt++] = card;
			}
			if (cardCnt == GameLogic.MAX_PLAY_CARD) {
				break;
			}
		}

		// 从牌堆中去除这些选中的牌,加入到战斗牌中
		for (ICard card : marchCards) {
			if (card != null) {
				battleCards.add(card);
				cards.remove(card);
			}
		}

		// 清除选中标志
		for (ICard card : cards) {
			card.setSelected(false);
		}

		return marchCards;
	}

	/**
	 * 将牌插入到手牌中的合适位置
	 * 
	 * @param card
	 */
	public void insertCard(ICard card) {
		int idx;
		for (idx = 0; idx < cards.size(); idx++) {
			if (card.getOrdinal() > cards.get(idx).getOrdinal()) {
				break;
			}
		}

		cards.add(idx, card);
	}

	@Override
	public int getCardCount() {
		return cards.size();
	}

	@Override
	public ICard[] getCards() {
		return cards.toArray(new ICard[cards.size()]);
	}

	@Override
	public void deselectCard(int index) {
		if (index < 0 || index >= cards.size()) {
			return;
		}

		ICard card = cards.get(index);
		card.setSelected(false);
	}

	@Override
	public void selectCard(int index) {
		if (index < 0 || index >= cards.size()) {
			return;
		}

		ICard card = cards.get(index);
		card.setSelected(true);
	}

	@Override
	public ICard[] getSelectedCards() {
		ArrayList<ICard> sltCards = new ArrayList<ICard>();
		for (ICard card : cards) {
			if (card.isSelected()) {
				sltCards.add(card);
			}
		}

		return sltCards.toArray(new ICard[sltCards.size()]);
	}

	@Override
	public ICard[] takeSelectedCards() {
		ICard[] sltCards = getSelectedCards();
		for (ICard card : sltCards) {
			cards.remove(card);
		}

		return sltCards;
	}

	@Override
	public int getSelectedCardCount() {
		int sltCnt = 0;
		for (ICard card : cards) {
			if (card.isSelected()) {
				sltCnt++;
			}
		}
		return sltCnt;
	}

	@Override
	public void takeback(ICard[] backCards) {
		for (int i = 0; i < backCards.length; i++) {
			takeback(backCards[i]);
			backCards[i] = null;
		}
	}

	@Override
	public void takeback(ICard card) {
		if (card == null) {
			return;
		}

		card.setCovered(false);
		card.setSelected(false);
		insertCard(card);
	}

	@Override
	public void changeCard() {
		for (int i = cards.size() - 1; i >= 0; i--) {
			if (cards.get(i).isSelected()) {
				cardPile.takeBack(cards.get(i));
				cards.remove(i);
				break;
			}
		}
	}

	public boolean isAlive() {
		return isAlive;
	}

	public boolean isVictorior() {
		for (IPlayer player : game.getPlayers()) {
			if (player.isAlive() && player.getMaster() != this) {
				return false;
			}
		}

		return true;
	}

	@Override
	public void revitalize(IPlayer master, ICard[] sendCards) {
		// 记录复活消息
		GameMsg msg = new GameMsg(0);
		msg.addPlayer(getPlayerName());
		msg.add(" 成为  ", Color.RED);
		msg.addPlayer(master.getPlayerName());
		msg.add(" 势力.", Color.RED);
		game.getGameRecorder().add(msg);

		// 为自己记录一次被复活,为master记录一次复活
		statsInfo.record(StatsInfo.ST_BE_REVITALIZED);
		master.getStatsInfo().record(StatsInfo.ST_REVITALIZE);
		game.addBonus(5);

		this.isAlive = true;
		this.force = master.getForce();
		this.force.addMember(this);

		// 需要主公提供的三张牌,从牌堆里面取三张牌,一共六张牌复活.
		for (ICard card : sendCards) {
			card.clearAllFlags();
			card.clearAllSkills();
			insertCard(card);
		}

		for (int i = 0; i < 3; i++) {
			drawCard();
		}
	}

	@Override
	public void independ() {

		// 弃掉大王和小王
		boolean discardBlackJoker = false;
		boolean discardRedJoker = false;
		Iterator<ICard> it = cards.iterator();
		while (it.hasNext()) {
			ICard card = it.next();
			if (card.isBlackJoker() && !discardBlackJoker) {
				game.getCardPile().takeBack(card);
				it.remove();
				discardBlackJoker = true;
				continue;
			}

			if (card.isRedJoker() && !discardRedJoker) {
				game.getCardPile().takeBack(card);
				it.remove();
				discardRedJoker = true;
				continue;
			}

			if (discardBlackJoker && discardRedJoker) {
				break;
			}
		}

		this.force.changeMaster(this);
	}

	public String getPlayerName() {
		return name;
	}

	public int getPortraitId() {
		return portraitId;
	}

	public void setPortrait(int portraitId) {
		this.portraitId = portraitId;
	}

	public Pos getPosition() {
		return this.pos;
	}

	public void setPosition(int px, int py) {
		this.pos.x = px;
		this.pos.y = py;
	}

	@Override
	public IPlayer getMaster() {
		return (this.force == null) ? null : this.force.getMaster();
	}

	@Override
	public void defeated() {
		this.isAlive = false;

		// 记录统计信息
		this.statsInfo.record(StatsInfo.ST_BE_CONQUERED);
		if (atkSource != null) {
			atkSource.getStatsInfo().record(StatsInfo.ST_CONQUER);
		}

		// 如果被灭的是主公,则需要重新选举一个新的主公继承该势力.
		// 这个在remove中已经做了
		this.force.removeMember(this);

		// 更改force为新的force
		this.force = (atkSource != null) ? atkSource.getForce() : null;
		if (force != null) {
			force.addMember(this);
		}
	}

	@Override
	public void reset() {
		this.cards.clear();
		this.isAlive = true;
		this.isAttacker = false;
		this.isDefender = false;
		this.hasGeneral = false;
		this.force = new Force(this);
		this.statsInfo.clear();
		this.isDone = false;

		for (int i = 0; i < actionMask.length; i++) {
			actionMask[i] = false;
		}
	}

	@Override
	public Action getAction() {
		return this.action;
	}

	@Override
	public void setAction(Action action) {
		GameMsg msg = new GameMsg(0);
		msg.addPlayer(getPlayerName());
		msg.add(" 选择了 ");
		msg.addAction(action);
		game.getGameRecorder().add(msg);

		this.action = action;
	}

	@Override
	public boolean isAttacker() {
		return isAttacker;
	}

	@Override
	public void setAttackTarget(IPlayer player) {
		if (atkTarget != null) {
			atkTarget.setAttackSource(null);
		}

		if (player == null) {
			isAttacker = false;
			atkRoute = null;
			atkTarget = null;
			return;
		}

		isAttacker = true;
		atkTarget = player;

		int rightAtkDis = GameUtils.getRightAtkDistance(this, atkTarget);
		int leftAtkDis = GameUtils.getLeftAtkDistance(this, atkTarget);

		if (rightAtkDis != leftAtkDis) {
			atkClockwise = (rightAtkDis < leftAtkDis) ? false : true;
		} else {
			int srcIdx = this.index;
			int destIdx = atkTarget.getPlayerIndex();

			int rightAbsDis = (destIdx >= srcIdx) ? destIdx - srcIdx : destIdx - srcIdx + GameLogic.MAX_PLAYER_COUNT;
			int leftAbsDis = (srcIdx >= destIdx) ? srcIdx - destIdx : srcIdx - destIdx + GameLogic.MAX_PLAYER_COUNT;
			atkClockwise = (rightAbsDis <= leftAbsDis) ? false : true;
		}
		atkRoute = new AttackRoute(game, this, atkClockwise);

		player.setAttackSource(this);

		GameMsg msg = new GameMsg(0);
		msg.add(getPlayerName(), Color.YELLOW);
		msg.add(" 选择进攻 ");
		msg.add(player.getPlayerName(), Color.YELLOW);
		game.getGameRecorder().add(msg);
	}

	@Override
	public IPlayer getAttackTarget() {
		return this.atkTarget;
	}

	@Override
	public boolean isDefender() {
		return isDefender;
	}

	@Override
	public void setAttackSource(IPlayer player) {
		if (player == null) {
			isDefender = false;
			return;
		}

		isDefender = true;
		this.atkSource = player;
	}

	@Override
	public IPlayer getAttackSource() {
		return this.atkSource;
	}

	@Override
	public IAttackRoute getAttackRoute() {
		return this.atkRoute;
	}

	@Override
	public IPlayer getLeftPlayer() {
		int idx = getPlayerIndex(this);
		if (idx == -1) {
			return null;
		}

		idx--;
		if (idx == -1) {
			idx = game.getPlayerCount() - 1;
		}

		return game.getPlayers()[idx];
	}

	@Override
	public IPlayer getLeftAlivePlayer() {

		int idx = getPlayerIndex(this);
		if (idx == -1) {
			return null;
		}

		IPlayer[] players = game.getPlayers();
		int i = idx;
		do {
			i--;
			if (i == -1) {
				i = game.getPlayerCount() - 1;
			}
		} while (!players[i].isAlive() && i != idx);

		return players[i];
	}

	@Override
	public IPlayer getRightPlayer() {
		int idx = getPlayerIndex(this);
		if (idx == -1) {
			return null;
		}

		idx++;
		if (idx == game.getPlayerCount()) {
			idx = 0;
		}

		return game.getPlayers()[idx];

	}

	@Override
	public IPlayer getRightAlivePlayer() {

		int idx = getPlayerIndex(this);
		if (idx == -1) {
			return null;
		}

		IPlayer[] players = game.getPlayers();
		int i = idx;
		do {
			i++;
			if (i == players.length) {
				i = 0;
			}
		} while (!players[i].isAlive() && i != idx);

		return players[i];

	}

	private int getPlayerIndex(IPlayer player) {
		IPlayer[] players = game.getPlayers();
		for (int i = 0; i < players.length; i++) {
			if (player == players[i]) {
				return i;
			}
		}

		return -1;
	}

	@Override
	public void handle() {
		// 如果不在等待状态列表中的话，说明不需要用户参与，直接将done设为true
		IState gameState = game.getState();
		if (!gameState.isWaitInput()) {
			setDone(true);

		}
	}

	@Override
	public boolean isDone() {
		return this.isDone;
	}

	@Override
	public void setDone(boolean isDone) {
		this.isDone = isDone;
	}

	@Override
	public float getTimeLeft() {
		return this.timeLeft;
	}

	@Override
	public void setTimeLeft(float timeLeft) {
		this.timeLeft = (timeLeft >= 0) ? timeLeft : 0;
	}

	public void elapse(float dt) {
		timeLeft -= dt;
		timeLeft = (timeLeft >= 0) ? timeLeft : 0;
	}

	@Override
	public IPlayerInfo getPlayerInfo() {
		return this.playerInfo;
	}

	@Override
	public IForce getForce() {
		return this.force;
	}

	@Override
	public void clearForce() {
		this.force = null;
	}

	@Override
	public int getPlayerIndex() {
		return this.index;
	}

	@Override
	public void setPlayerIndex(int index) {
		this.index = index;
	}

	@Override
	public void withdraw() {
		// 将battleCards放回到手牌中
		Iterator<ICard> it = battleCards.iterator();
		while (it.hasNext()) {
			ICard card = it.next();
			card.clearAllFlags();
			card.clearAllSkills();

			insertCard(card);
			it.remove();
		}
	}

	@Override
	public IStatsInfo getStatsInfo() {
		return this.statsInfo;
	}

	@Override
	public IPlayer getCallSource() {
		return this.callSource;
	}

	@Override
	public IPlayer getSendTarget() {
		return this.sendTarget;
	}

	@Override
	public void setCallSource(IPlayer source) {
		this.callSource = source;
	}

	@Override
	public void setSendTarget(IPlayer target) {
		this.sendTarget = target;
	}

	@Override
	public boolean[] getActionMask() {
		return this.actionMask;
	}

	@Override
	public void setMandate(boolean isMandate) {
		isHuman = !isMandate;
	}

	@Override
	public List<ICard> getBattleCards() {
		return this.battleCards;
	}

}
